#include <iostream>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <cstring>
#include <string>
#include <pthread.h>
#include "log.hpp"
#define BUFFERSIZE 1024

Log lg(SCREEN);
pthread_mutex_t mutex_screen = PTHREAD_MUTEX_INITIALIZER;

class manual
{
public:
    void operator()(const char *str)
    {
        printf("%s ip port\n", str);
    }
};

struct thread_argv
{
    thread_argv(int sock_fd, struct sockaddr_in internet_struct)
        : sock_fd_(sock_fd), internet_struct_(internet_struct)
    {
    }
    int sock_fd_;
    struct sockaddr_in internet_struct_;
};

void *thread_send_fun(void *_argv)
{
    thread_argv *server = (thread_argv *)_argv;
    while (true)
    {
        std::string message;
        std::cout << "input:";
        std::getline(std::cin, message);
        socklen_t server_len = sizeof(server->internet_struct_);
        sendto(server->sock_fd_, message.c_str(), message.size(), 0, (sockaddr *)&server->internet_struct_, server_len);
    }
    return nullptr;
}

void *thread_recv_fun(void *argv)
{
    int *sock_fd = (int *)argv;
    while (true)
    {
        sockaddr_in temp;
        socklen_t len = sizeof(temp);
        char inbuffer[BUFFERSIZE];
        size_t n = recvfrom(*sock_fd, inbuffer, sizeof(inbuffer), 0, (sockaddr *)&temp, &len);
        inbuffer[n] = 0;
        std::cout << inbuffer << std::endl;
        // std::cout << inet_ntoa(temp.sin_addr) << std::endl;//会得到服务器的ip
        //客户端只会拿到服务端ip,为什么ip中是有表明目的IP和源ip的，源IP不用用户提供，大胆猜测就是操作系统自己填上去了
    }
    return nullptr;
}

int main(int argc, char *argv[])
{
    manual man;
    // 需要知道服务器ip和他的端口号
    if (argc < 3)
    {
        man(argv[0]);
        exit(1);
    }
    // sockfd
    int sock_fd = socket(AF_INET, SOCK_DGRAM, 0);
    if (sock_fd == -1)
    {
        lg(FATAL, "fd creation failed! %d:%s", errno, strerror(errno));
        exit(1);
    }
    lg(INFO, "fd creation success! %d:%s", errno, strerror(errno));
    // bind 不用手动绑定

    // 端口 ip 结构体
    struct sockaddr_in server;
    bzero(&server, sizeof(server));
    server.sin_family = AF_INET; // ipv4
    server.sin_addr.s_addr = inet_addr(argv[1]);
    server.sin_port = htons(std::stoi(argv[2]));
    socklen_t server_len = sizeof(server);
    lg(INFO, "struct create success");
    // sendto

    thread_argv t_argv(sock_fd, server);
    pthread_t send_tid;
    pthread_create(&send_tid, nullptr, thread_send_fun, (void *)&t_argv);
    pthread_t recv_tid;
    pthread_create(&recv_tid, nullptr, thread_recv_fun, (void *)&sock_fd);

    pthread_join(send_tid, nullptr);
    pthread_join(recv_tid, nullptr);
    return 0;
}
